'use client';

import PresaleTemplate, {
  type FetchRequestWithController,
} from '@/components/templates/presale/template';
import { ErrorState } from '@/components/ui/error';
import FlowChain from '@/components/plans/generate';
import { useReport } from '@/hooks/useReport';
import { useDownload } from '@/hooks/useDownload';
import { useUpload } from '@/hooks/useUpload';
import { Button, Card, Modal, Select, Toast } from '@douyinfe/semi-ui';
import type { FormApi } from '@douyinfe/semi-ui/lib/es/form';
import { Icon } from '@iconify/react';
import { memo, useCallback, useRef, useState, useMemo } from 'react';
import type { Parameter } from '@/app/api/plans/route';
import { clientFetch } from '@/utils/request';
import { DocxContext } from '@/contexts/DocxContext';

const MemoizedFlowChain = memo(FlowChain);

export default function PlanPage() {
  const [selectedTemplate, setSelectedTemplate] =
    useState<string>('template01');
  const [currentView, setCurrentView] = useState<'form' | 'generate'>('form');
  const [visible, setVisible] = useState<boolean>(false);
  const [loading, setLoading] = useState<boolean>(false);
  const [isError, setIsError] = useState<boolean>(false);
  const [retryCount, setRetryCount] = useState<number>(0);
  const [requests, setRequests] = useState<FetchRequestWithController[]>();
  const wordRef = useRef<Blob>();
  const docParameterRef = useRef<Parameter[]>([]);
  const docxRef = useRef({});

  const { render, rendering } = useReport();

  const formData = useRef<any>();
  const formRef = useRef<FormApi | null>(null);

  const { upload, isUploading } = useUpload();
  const { download, downloading } = useDownload();

  const switchView = useCallback((newView: 'form' | 'generate') => {
    setCurrentView(newView);
  }, []);

  const handleError = useCallback((error: Error) => {
    Toast.error(error.message);
    setIsError(true);
  }, []);

  const handleSavePlan = async () => {
    if (!wordRef.current) {
      return;
    }

    const uploadRes = await upload(new File([wordRef.current!], `test.docx`));

    const res = await clientFetch.post('/api/plans', {
      creator: '张工程师',
      status: 'private',
      file: {
        ...uploadRes.data,
      },
      parameter: docParameterRef.current,
      template: '售前方案',
      version: 'V1',
    });

    if (res.code === 200) {
      Toast.success('方案已保存到云端');
    } else {
      Toast.error('方案保存到云端失败，如需要请及时下载');
    }
  };

  // AI 响应结束
  const handleFinished = async () => {
    // 生成 docx
    await generateDoc(docxRef.current);

    // 保存 docx
    await handleSavePlan();
  };

  // 下载 docx 文件
  const handleDownload = async () => {
    if (!wordRef.current) {
      return;
    }

    download(wordRef.current!, {
      filename: 'text.docx',
    });
  };

  // 渲染 docx
  const generateDoc = useCallback(async (data: any) => {
    console.log(docxRef.current);

    const doc = await render({
      convertTo: 'docx',
      data,
    });
    wordRef.current = doc as unknown as Blob;
  }, []);

  const handleRetry = useCallback(() => {
    setRetryCount((prev) => {
      console.log(prev);
      setIsError(false);
      return prev + 1;
    });
  }, []);

  const showDialog = useCallback(() => {
    setVisible(true);
  }, []);

  const handleGenerate = async () => {
    try {
      formRef.current?.submitForm();
    } catch {
      Toast.info('请填写需要填写的参数');
    }
  };

  const handleBack = useCallback(() => {
    setCurrentView('form');
  }, []);

  const handleOk = useCallback(() => {
    setVisible(false);
    switchView('form');
  }, [switchView]);

  const handleCancel = useCallback(() => {
    setVisible(false);
    console.log('Cancel button clicked');
  }, []);

  // 表单组件
  const FormView = useMemo(
    () => (
      <div className="min-h-[376px] rounded-xl border-semi-color-border p-8">
        <Card title="选择模板">
          <Select
            className="w-[176px]"
            defaultValue="template01"
            onChange={(value) => {
              setSelectedTemplate(value as string);
            }}
            size="large"
          >
            <Select.Option value="template01">售前方案模板</Select.Option>
            <Select.Option value="template02">模板 2</Select.Option>
          </Select>
        </Card>
        {selectedTemplate === 'template01' && (
          <PresaleTemplate
            getFormApi={(formApi) => (formRef.current = formApi)}
            onSubmit={({ parameters, request, values }) => {
              docParameterRef.current = parameters;
              setRequests(request);
              formData.current = values;
              console.log('props:', parameters, request, values);
              // 切换界面
              switchView('generate');
            }}
          ></PresaleTemplate>
        )}

        <Button
          type="primary"
          onClick={handleGenerate}
          className="mx-auto mt-6 block min-w-[176px]"
          loading={loading}
          size="large"
          icon={<Icon icon="mingcute:magic-2-line" />}
        >
          生成设计方案
        </Button>
      </div>
    ),
    [selectedTemplate]
  );

  // 生成页面组件 - 使用 useMemo 缓存
  const GenerateView = useMemo(
    () => (
      <div>
        <Button
          icon={<Icon icon="mingcute:left-line" fontSize={18}></Icon>}
          onClick={showDialog}
          className="mb-[24px]"
          disabled={loading}
        >
          返回
        </Button>
        {isError ? (
          <ErrorState onRetry={handleRetry} onBack={handleBack} />
        ) : (
          <div className="mx-auto w-[80%]">
            <MemoizedFlowChain
              onFinished={handleFinished}
              handleDownload={handleDownload}
              requestBody={requests!}
              onError={handleError}
              retryCount={retryCount}
              rendering={rendering}
              isDownload={downloading}
            />
          </div>
        )}
      </div>
    ),
    [
      showDialog,
      loading,
      isError,
      handleRetry,
      handleBack,
      generateDoc,
      requests,
      handleError,
      retryCount,
      rendering,
      downloading,
    ]
  );

  // 根据当前视图渲染对应组件
  return (
    <>
      <DocxContext.Provider value={{ docxRef }}>
        <div className="view-container">
          {currentView === 'form' ? FormView : GenerateView}
        </div>
      </DocxContext.Provider>
      <Modal
        title="返回确认"
        visible={visible}
        onOk={handleOk}
        onCancel={handleCancel}
        closeOnEsc={true}
      >
        <p className="text-semi-color-warning">
          此操作将取消当前正在生成的方案，无法恢复。
        </p>
      </Modal>
    </>
  );
}
